<?php

include_once('data.php');
include_once(Utils::getPath(array('model', 'solution.php')));
include_once(Utils::getPath(array('repositories', 'challengeRepository.php')));

class SolutionRepository {

    private $lastFilter;

    public function getById($solutionId) {
        if (is_numeric($solutionId)) {
            $row = Database::select('*', 'solutions', array(array('Id = ?', $solutionId, PDO::PARAM_INT)));

            if ($row->rowCount() == 1) {
                $solution = $row->fetchObject('Solution');
                return $solution;
            }
        }
        return null;
    }

    public function getAll($order = null, $desc = null, $pageIndex = 0, $pageCount = 10) {
        return $this->find(null, $order, $desc, $pageIndex, $pageCount);
    }

    public function findByChallenge($challengeId, $valid = null, $order = null, $desc = null, $pageIndex = 0, $pageCount = 10) {
        $filterParams = array();
        $filterParams[] = array("IdChallenge = ?", $challengeId, PDO::PARAM_INT);
        if ($valid != null) {
            $filterParams[] = array("AND Valid = ?", (int) $valid, PDO::PARAM_BOOL);
        }
        return $this->find($filterParams, $order, $desc, $pageIndex, $pageCount);
    }

    public function findByAuthor($authorId, $valid = null, $order = null, $desc = null, $pageIndex = 0, $pageCount = 10) {
        $filterParams = array();
        $filterParams[] = array("IdAuthor = ?", $authorId, PDO::PARAM_INT);

        return $this->find($filterParams, $valid, $order, $desc, $pageIndex, $pageCount);
    }

    public function findByChallengeAuthor($challengeAuthor, $filterParams, $valid = null, $order = null, $desc = null, $pageIndex = 0, $pageCount = 10) {
        $strfilter = '';
        if (count($filterParams) > 0)
            $strfilter = ' AND ';
        $filterParams[] = array($strfilter . "challenges.IdAuthor = ?", $challengeAuthor, PDO::PARAM_INT);
        if ($valid != null) {
            $filterParams[] = array("AND Valid = ?", (int) $valid, PDO::PARAM_BOOL);
        }
        $rows = Database::select('solutions.Id AS Id, solutions.IdChallenge AS IdAuthor, solutions.IdAuthor AS IdAuthor, solutions.Description AS Description, solutions.Valid AS Valid, solutions.Quality AS Quality, solutions.FilePath AS FilePath, solutions.Date AS Date', 'solutions JOIN challenges ON solutions.IdChallenge = challenges.Id', $filterParams, $order, $desc, $pageIndex * $pageCount, $pageCount);

        if ($rows->rowCount() > 0) {
            $comments = $rows->fetchAll(PDO::FETCH_CLASS, "Solution");
            return $comments;
        }
        return null;
    }
    
    public function findMySolutions($userId)
    {
        $query = "SELECT
                    my_solutions.id AS solutionid,
                    all_challenges.id AS challengeid,
                    all_challenges.title AS challengetitle,
                    valid,
                    quality,
                    date
                FROM
                    (SELECT
                        id, idchallenge, idauthor, valid, quality, date 
                    FROM 
                        solutions
                    WHERE 
                        idauthor = :id
                    ) AS my_solutions
                LEFT JOIN
                    (SELECT
                        id,
                        title
                    FROM 
                        challenges
                    ) AS all_challenges
                ON all_challenges.id = my_solutions.idchallenge

                ORDER BY date DESC";
        
        $arguments = array();
        $arguments[] = array(":id", $userId, PDO::PARAM_INT);

        $solutions = Database::customQuery($query, $arguments)->fetchAll();
        
        return $solutions;
    }
    
    public function findUncheckedByMe($userId)
    {
        $query = "SELECT
                    my_solutions.id AS solutionid,
                    all_challenges.id AS challengeid,
                    all_challenges.title AS challengetitle,
                    all_users.id AS authorid, 
                    all_users.username AS authorusername,
                    valid,
                    quality,
                    date
                FROM
                    (SELECT
                        id, idchallenge, idauthor, valid, quality, date 
                    FROM 
                        solutions
                    WHERE 
                        isnull(valid) AND 
                        idchallenge IN 
                            (SELECT id FROM challenges WHERE idauthor = :id)
                    ) AS my_solutions
                LEFT JOIN
                    (SELECT
                        id,
                        title
                    FROM 
                        challenges
                    ) AS all_challenges
                ON all_challenges.id = my_solutions.idchallenge
                LEFT JOIN
                    (SELECT 
                        id,
                        username
                    FROM users
                    ) AS all_users
                ON all_users.id = my_solutions.idauthor    

                ORDER BY date DESC";

        $arguments = array();
        $arguments[] = array(":id", $userId, PDO::PARAM_INT);

        $solutions = Database::customQuery($query, $arguments)->fetchAll();
        
        return $solutions;
    }

    public function find($filterParams, $valid = null, $order = null, $desc = null, $pageIndex = 0, $pageCount = 10) {
        if ($valid != null) {
            $filterParams[] = array("AND Valid = ?", (int) $valid, PDO::PARAM_BOOL);
        }
        $rows = Database::select('*', 'solutions', $filterParams, $order, $desc, $pageIndex * $pageCount, $pageCount);
        $this->lastFilter = $filterParams;
        if ($rows->rowCount() > 0) {
            $solutions = $rows->fetchAll(PDO::FETCH_CLASS, "Solution");
            return $solutions;
        }
        return null;
    }

    public function countLast() {
        $rows = Database::select('Count(*)', 'solutions', $this->lastFilter, null, null, null, null);
        $count = $rows->rowCount();
        if ($count == 1) {
            $row = $rows->fetch(PDO::FETCH_NUM);
            return $row[0];
        }
        return null;
    }

    public function sumQuality($filter = null) {
        if ($filter == null)
            $filter = $this->lastFilter;
        $rows = Database::select('SUM(Quality)', 'solutions', $filter, null, null, null, null);
        $count = $rows->rowCount();
        if ($count == 1) {
            $row = $rows->fetch(PDO::FETCH_NUM);
            return $row[0];
        }
        return null;
    }

    private function getLast() {
        $row = Database::select('*', 'solutions', null, 'Id', true, 0, 1);

        if ($row->rowCount() == 1) {
            $solution = $row->fetchObject('Solution');
            return $solution;
        }
        return null;
    }

    public function persist($solution) {
        $values = array();

        $values[] = array('Id', $solution->getId(), PDO::PARAM_INT);
        $values[] = array('IdChallenge', $solution->getIdChallenge(), PDO::PARAM_INT);
        $values[] = array('IdAuthor', $solution->getIdAuthor(), PDO::PARAM_INT);
        $values[] = array('Description', $solution->getDescription(), PDO::PARAM_STR);
        $values[] = array('Valid', $solution->getValid(), PDO::PARAM_BOOL);
        $values[] = array('Quality', $solution->getQuality(), PDO::PARAM_INT);
        $values[] = array('FilePath', $solution->getFilePath(), PDO::PARAM_STR);
        $values[] = array('Date', $solution->getDate(), PDO::PARAM_STR);

        if (!$solution->IsPersited()) {
            $res = Database::insert('solutions', $values);
            if ($res)
                return $this->getLast();
        }
        else {
            $res = DataBase::update('solutions', $values, array(array('Id = ?', $solution->getId(), PDO::PARAM_INT)));
            if ($res)
                return $this->getById($solution->getId());
        }

        return null;
    }

    public function remove($solution) {
        $res = Database::remove('solutions', array(array('Id = ?', $solution->getId(), PDO::PARAM_INT)));
        return $res;
    }

    public function userCanAccessSolution($userId, $solution) {
        $challengeId = $solution->getIdChallenge();
        $chaRep = new ChallengeRepository();
        $challenge = $chaRep->getById($challengeId);
        
                
        $user_is_challenge_author = ($challenge->getIdAuthor() == $userId);
        $user_is_solution_author = ($solution->getIdAuthor() == $userId);
        $filterParams = array();
        $filterParams[] = array("idauthor = ? AND ", $userId, PDO::PARAM_INT);
        $filterParams[] = array("idchallenge = ?", $solution->getIdChallenge(), PDO::PARAM_INT);
        
        $valid_user_solutions = $this->find($filterParams, true);

        $user_can_see_solution = $user_is_challenge_author || $user_is_solution_author || count($valid_user_solutions) > 0;
        return $user_can_see_solution;
    }
    
    public function getSolutionsWithAuthorName($id)
    {
        $query = "SELECT 
                        solutions.id AS solutionid, 
                        username,
                        users.id AS userid,
                        valid,
                        quality,
                        date

                    FROM
                            solutions
                        LEFT JOIN
                            users
                        ON solutions.idauthor = users.id
                    WHERE idchallenge = :id
                    ORDER BY date";

        $arguments = array();
        $arguments[] = array(":id", $id, PDO::PARAM_INT);

        $solutions = Database::customQuery($query, $arguments)->fetchAll();
        
        return $solutions;
    }

}

?>